October 19, 2016

Ilastik Membrane Detection

Decision Tree and Random Forest

Decision trees are a type of regression technique that aims to discern some set of discrete features from a data set. Decision trees function are built from a subset of branches (specific features) and nodes (where the branches split).

Carving Technique

To do membrane detection in Ilastik, I first followed the carving technique. Carving refers to separating individual objects by their boundaries (which is unlike what classification does -- classification looks at the individual brightness values to try to determine differences in the internal structure, while carving functions primarily by examining borders).

I used their suggested mouse retina EM data courtesy Winfried Dink et al, and managed to get some results that were relatively interesting. I started with this because this looked like the most generic case for membrane detection - after I actually familiarized myself with our data, it turns out carving won't work. Still, it had some pretty images, so I included them here.

Classification Process

After visualizing Fear200 on ndviz, I discovered that carving won't work -- we're going to need the traditional classification process.

What classification does is that it uses a 'trained' classifier that somebody (like me) generates on a subset of data. From the classifier, it then applies the transformation to the entire data set hopefully to generate some positive results.

Following the script for ndod and image classification, I started with a 2D TIFF image screencap conversion of Fear200 from ndviz (coordinates: 2264, 991, 0).

To generate the initial classifier, I used the heads-up display (GUI interface) for Ilastik to manually select bright points (red) and their respective backgrounds. Shown below is one image of the classification training for the bright point selection.

Following selecting both the background and the bright points, I then ran the initial feature training with the default settings.

I then proceeded to look at the output given my training. The results are below (see the green for the background label, the red for the bright point label).

I then exported the results as an h5 file directly to my working directory.

From there, I could run my predefined classifier from above on any set of sample data. To do so, you can use Ilastik in headless mode (directly from the terminal). An example of the shell prompt is below (this code uses the fear200 classifier project I did earlier and runs it headlessly on a different region of fear200).

/Applications/ilastik-1.2.0rc10-OSX.app/Contents/ilastik-release/run_ilastik.sh --headless --project=fear200.ilp --output_format=tiff fear200_611_1005_0_4.tiff

The results are then shown here. First, we have the raw TIFF of Fear200 (region coordinates from ndviz: (611, 1005, 0, 4)).

Now, after applying our classifier, this is TIFF version of the probability output.

Classification on Our Data (Example)

Since our data isn't stored as TIFFs (they're actually .nii files), I started by using the Docker Luke made that contains ndreg/ndio on our GoogleCloud server. I then modified an existing script we had to find the spacing for the .nii file I chose to use. The script is below:


In [ ]:
## Titled getspacing.py

from ndreg import *
import matplotlib
import ndio.remote.neurodata as neurodata
import nibabel as nb
inToken = 'Fear197'
inImg = imgDownload(inToken, resolution=5)
print(inImg.GetSpacing())

I then modified a script Albert wrote last week that downsamples these .nii files. I used that script and used 1/100th of the spacing generated from above. Thus, the spacing was (0.0032, 0.0032, 0.0001)


In [ ]:
## Script used to downsample nii to manageable size
from ndreg import *
import matplotlib
import ndio.remote.neurodata as neurodata
import nibabel as nb
inToken = "Fear197"
nd = neurodata()
print(nd.get_metadata(inToken)['dataset']['voxelres'].keys())
inImg = imgDownload(inToken, resolution=5)
inImg = imgResample(inImg, spacing=(0.0032, 0.0032, 0.0001))
imgWrite(inImg, "./Fear199ds100.nii")

I then got the file from the server onto my local computer. I then wrote some code (see this other Jupyter notebook I made here: https://neurodatadesign.github.io/seelviz/Jupyter/ilastik/NIFTIAndIlastikMembraneDetection.html) that converts the .nii file into an np array and saves each individual plane as a TIFF.

From documentation, 3D grayscale is organized such that we effectively have (pln, row, col),where pln is plane, row is row and column is column. Elements at the top left have the lowest brightness value, while elements in the bottom right have the highest brightness values.

My script converts each plane into a TIFF output, and saves the output TIFFs accordingly. Now, I'm going to repeat the process I ran with the screencapped file and then apply this classification to each layer of the NIFTI image.

Since the 100x downsampled versions were simply too small (1kb), I reran the script on Fear197 downsampled only 10x. (Changing the spacing to 10x instead of 100x). Thus, the .nii was around 11 MB

From there, I repeated the entire process from earlier using outfileFear197ds10.nii12 (layer12) as the training file. Below is the training process on plane 12.

The raw image for plane 12 is shown below:

First, draw preliminary labels.

Now, see live results. When satisfied, export as TIFF probability mapping.

We can now open the results and compare them with our original.

Original:

Post Ilastik:

From there, we can run our headless commands as discussed earlier. As I discussed with Greg, the main follow up from here is to:

1) Ascertain how reasonable these results are

 * We can do this either by taking these images, finding the bright points therein, and then comparing these       bright points to our histogram equalization based point cloud representation.

2) Automate progress further, such that I can load images much faster.

As for all the pseudocode, it can be found here: https://www.overleaf.com/6610849ssmpyy#/22404584/

Miscellania:

1) Could not get token Fear200 from ndreg -- throws error (see below) 2) Need to figure out a way to orient the brains such that the TIFF slices for the planes is more accurate (currently kinda random process)


In [ ]:
## Running on inToken Fear200 error (so used Fear199 and Fear197 instead)

[u'1', u'0', u'3', u'2', u'5', u'4']
Traceback (most recent call last):
  File "tony.py", line 10, in <module>
    inImg = imgDownload(inToken, resolution=5)
  File "/root/.local/lib/python2.7/site-packages/ndreg-0.0.1-py2.7.egg/ndreg/ndreg.py", line 152, in imgDownload
    array = nd.get_cutout(token, channel, offset[0], size[0], offset[1], size[1], offset[2], size[2], resolution)
  File "build/bdist.linux-x86_64/egg/ndio/remote/neurodata.py", line 97, in wrapped
  File "build/bdist.linux-x86_64/egg/ndio/remote/neurodata.py", line 572, in get_cutout
  File "build/bdist.linux-x86_64/egg/ndio/remote/neurodata.py", line 633, in _get_cutout_blosc_no_chunking
IOError: Bad server response for http://openconnecto.me/ocp/ca/Fear200/Grayscale/blosc/5/0,557/0,721/16,32/: 404: (
2003, "Can't connect to MySQL server on 'dsp063.pha.jhu.edu' (111)")
from ndreg import *

In [ ]: